package com.ruoyi.client.util;

import com.ruoyi.client.exception.JeepayException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.*;

/**
 * 签名工具类
 */
@Slf4j
public class SignatureUtil {

    /**
     * MD5签名
     * @param params 参数
     * @param appSecret 密钥
     * @return 签名值
     */
    public static String md5Sign(Map<String, Object> params, String appSecret) {
        // 参数按照字典序排序
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        // 构建签名字符串
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            Object value = params.get(key);
            if (value != null && !"sign".equals(key)) { // 排除sign字段
                sb.append(key).append("=").append(value).append("&");
            }
        }
        sb.append("key=").append(appSecret);

        // 进行MD5签名
        String plainText = sb.toString();
        log.debug("MD5签名原文: {}", plainText);
        String sign = DigestUtils.md5Hex(plainText).toUpperCase();
        log.debug("MD5签名结果: {}", sign);
        return sign;
    }

    /**
     * RSA2签名
     * @param params 参数
     * @param privateKey 私钥
     * @return 签名值
     * @throws JeepayException Jeepay异常
     */
    public static String rsa2Sign(Map<String, Object> params, String privateKey) throws JeepayException {
        try {
            // 参数按照字典序排序
            List<String> keys = new ArrayList<>(params.keySet());
            Collections.sort(keys);

            // 构建签名字符串
            StringBuilder sb = new StringBuilder();
            for (String key : keys) {
                Object value = params.get(key);
                if (value != null && !"sign".equals(key)) { // 排除sign字段
                    sb.append(key).append("=").append(value).append("&");
                }
            }
            // 去除最后一个&
            String content = sb.toString();
            if (content.endsWith("&")) {
                content = content.substring(0, content.length() - 1);
            }

            log.debug("RSA2签名原文: {}", content);

            // 处理私钥
            privateKey = privateKey.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replace("\r", "").replace("\n", "");

            // 进行RSA2签名
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(priKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            byte[] signed = signature.sign();

            String sign = Base64.getEncoder().encodeToString(signed);
            log.debug("RSA2签名结果: {}", sign);
            return sign;
        } catch (Exception e) {
            log.error("RSA2签名异常", e);
            throw new JeepayException("RSA2签名异常: " + e.getMessage(), e);
        }
    }
}
